import cn.lyh.annotation.AutoWired;
import cn.lyh.annotation.Bean;
import cn.lyh.annotation.Component;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class ApplicationContext<T> {

    private static Map<Class,Object> beanFactory = new HashMap<Class,Object>();
    private String filePath;

    public T getClass(Class clazz){
        return (T)beanFactory.get(clazz);
    }

    /**
     * 根据配置文件注入对象
     */
    public void initContext(){
        InputStream stream = ApplicationContext.class.getClassLoader().getResourceAsStream("config.properties");
        Properties properties = new Properties();
        try {
            properties.load(stream);
            Set<Object> keySet = properties.keySet();
            for(Object object :keySet){
                beanFactory.put(Class.forName(object.toString()),
                        Class.forName(properties.getProperty(object.toString())).newInstance());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 根据注解注入对象
     */
    public void initContextByAnnotation(){
        filePath= ApplicationContext.class.getClassLoader().getResource("").getFile();
        loadOne(new File(filePath));
        assembleObject();
    }

    private void loadOne(File parentFile){
        if(parentFile.isDirectory()){
            File[] childrenFiles = parentFile.listFiles();
            if(childrenFiles==null||childrenFiles.length==0){
                return;
            }
            for (File childrenFile:childrenFiles){
                //是目录，递归
                if(childrenFile.isDirectory()){
                    loadOne(childrenFile);
                }else{//非目录
                    String pathWithClass = childrenFile.getAbsolutePath().substring(filePath.length()-1);
                    if(pathWithClass.contains(".class")){
                        String fullName = pathWithClass.replaceAll("\\\\",".").replace(".class","");
                        try {
                            Class aClass = Class.forName(fullName.toString());
                            Annotation annotation = aClass.getAnnotation(Component.class);
                                if(annotation!=null){
                                    if(aClass.getInterfaces().length>0){
                                        //有接口
                                        System.out.println(aClass.getInterfaces()[0]+"注入成功，实例对象是"+aClass.getName());
                                        beanFactory.put(aClass.getInterfaces()[0],aClass.newInstance());
                                    }else {
                                        System.out.println(aClass+"注入成功，实例对象是"+aClass.getName());
                                        beanFactory.put(aClass,aClass.newInstance());
                                    }
                                }
                        }catch (Exception e){
                            e.printStackTrace();
                        }


                    }
                }

            }


        }
    }

    /**
     * 属性注入
     */
    public  void assembleObject(){
    for(Map.Entry<Class,Object> entry: beanFactory.entrySet()){
        Object obj = entry.getValue();
        Field[] fields = obj.getClass().getDeclaredFields();
        if(fields.length>0){
                for(Field field :fields){
                    AutoWired annotation = field.getAnnotation(AutoWired.class);
                    if (annotation!=null){
                       field.setAccessible(true);
                       try {
                           System.out.println(field.getType());
                           Class<?> aClass = field.getType();
                           if(aClass.getInterfaces().length>0){
                               System.out.println();
                               field.set(obj,beanFactory.get(aClass.getInterfaces()[0]));
                           }else {
                               field.set(obj,beanFactory.get(field.getType()));
                           }
                       }catch (Exception e){
                           e.printStackTrace();
                       }
                    }
                }
            }
        }
    }



    
}
